package aiSpeakerOperate

import (
	"AiSpeaker/constant"
	"AiSpeaker/internal/domain"
	"AiSpeaker/pkg/fastHttpInvoker"
	"AiSpeaker/pkg/logger"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
)

/**
 * 登陆
 */
func Login(server string, user string, passwd string) (string, error) {
	ip := checkUrl(server)
	url := ip + constant.DefaultSpeakerLogin
	loginRequest := &domain.AiSpeakerLoginRequest{}
	loginRequest.User = user
	loginRequest.Passwd = passwd
	respBytes, err := fastHttpInvoker.HttpPost(url, loginRequest, nil, nil)
	if err != nil {
		logger.Errorf("音柱服务登陆失败，%s", err.Error())
		return "", err
	}
	loginResponse := &domain.AiSpeakerLoginResponse{}
	err = json.Unmarshal(respBytes, loginResponse)
	if err != nil {
		logger.Errorf("音柱服务登陆响应解析失败，%s", err.Error())
		return "", err
	}
	return loginResponse.Value.Token, nil
}

/**
 * 创建音柱任务
 */
func CreateTask(server string, token string, deviceId int, audio int, second int, volume int) (int, error) {
	ip := checkUrl(server)
	url := ip + constant.DefaultSpeakerCreateTask
	now := time.Now()
	start := now.Hour()*constant.TenThousand + now.Minute()*constant.OneHundred + now.Second()
	end := start + constant.TenThousand
	name := "task_" + strconv.FormatInt(int64(deviceId), 10) + "_" + strconv.FormatInt(int64(audio), 10) + "_ " + strconv.FormatInt(now.UnixMilli(), 10)

	request := &domain.AiSpeakerCreateTaskRequest{
		PlanID:       1,
		Name:         name,
		Priority:     1,
		AudioSource:  0,
		FileIDs:      []int{audio},
		DeviceIDs:    []int{deviceId},
		StartTime:    start,
		EndTime:      end,
		WeekdayFlags: 3,
		PlayOrder:    0,
		Loop:         0,
		DurationType: 1,
		Duration:     second,
		Volume:       volume,
	}

	headers := make(map[string]string)
	headers["access_token"] = token
	respBytes, err := fastHttpInvoker.HttpPost(url, request, headers, nil)
	if err != nil {
		logger.Errorf("音柱服务创建任务失败，%s", err.Error())
		return constant.DefaultFailureCode, err
	}
	resp := &domain.AiSpeakerCreateTaskResponse{}
	err = json.Unmarshal(respBytes, resp)
	if err != nil {
		logger.Errorf("音柱服务创建任务响应解析失败，%s", err.Error())
		return constant.DefaultFailureCode, err
	}
	if resp.Code == 200 {
		return resp.Data.ID, nil
	}
	return constant.DefaultFailureCode, err
}

/**
 * 播放音柱音频
 */
func ExecuteTask(server string, token string, taskId int, second int) error {
	ip := checkUrl(server)
	url := ip + constant.DefaultSpeakerPlayTask
	url = fmt.Sprintf(url, taskId)

	headers := make(map[string]string)
	headers["access_token"] = token
	respBytes, err := fastHttpInvoker.HttpGet(url, "", headers, nil)

	if err != nil {
		logger.Errorf("播放音频失败，服务器：%s，任务id：%d，失败原因：%s", server, taskId, err.Error())
		return err
	}
	resp := &domain.SimpleResponse{}
	err = json.Unmarshal(respBytes, resp)
	if err != nil {
		logger.Errorf("音柱服务播放响应解析失败，%s", err.Error())
		return err
	}
	if resp.Code != 200 {
		return errors.New("音柱服务播放api调用失败")
	}

	/*
	 * 删除任务
	 */
	go func(sec int) {
		timeoutCxt, cancelFunc := context.WithTimeout(context.Background(), time.Second*time.Duration(sec))
		defer cancelFunc()
		select {
		case <-timeoutCxt.Done():
			code, _ := deleteTask(server, token, taskId)
			if code == 200 {
				logger.Infof("音柱任务删除成功，服务器：%s, taskId：%d", server, taskId)
			} else {
				//如果没有删除成功，过10秒在尝试删除
				timer := time.After(10 * time.Second)
				<-timer
				for i := 1; i <= 3; i++ {
					code, _ := deleteTask(server, token, taskId)
					if code == 200 {
						logger.Infof("音柱任务第%d次删除成功，服务器：%s, taskId：%d", i, server, taskId)
						return
					}
				}
			}
		}
	}(second + 1)

	return nil
}

/**
 * 停止任务
 */
func stopTask(server string, token string, taskId int) (int, error) {
	ip := checkUrl(server)
	url := ip + constant.DefaultSpeakerStopTask
	url = fmt.Sprintf(url, taskId)

	headers := make(map[string]string)
	headers["access_token"] = token
	respBytes, err := fastHttpInvoker.HttpDelete(url, "", headers, nil)

	if err != nil {
		logger.Errorf("停止任务失败，服务器：%s，任务id：%d，失败原因：%s", server, taskId, err.Error())
		return constant.DefaultFailureCode, err
	}
	resp := &domain.SimpleResponse{}
	err = json.Unmarshal(respBytes, resp)
	if err != nil {
		logger.Errorf("音柱服务停止任务响应解析失败，%s", err.Error())
		return constant.DefaultFailureCode, err
	}
	if resp.Code != 200 {
		logger.Errorf("音柱服务停止任务响应解析失败，%s", resp.Message)
		return constant.DefaultFailureCode, err
	}
	return resp.Code, nil
}

/**
 * 删除任务
 */
func deleteTask(server string, token string, taskId int) (int, error) {
	_, err := stopTask(server, token, taskId)
	if err != nil {
		return constant.DefaultFailureCode, err
	}
	ip := checkUrl(server)
	url := ip + constant.DefaultSpeakerDeleteTask
	url = fmt.Sprintf(url, taskId)

	headers := make(map[string]string)
	headers["access_token"] = token
	respBytes, err := fastHttpInvoker.HttpDelete(url, "", headers, nil)

	if err != nil {
		logger.Errorf("删除任务失败，服务器：%s，任务id：%d，失败原因：%s", server, taskId, err.Error())
		return constant.DefaultFailureCode, err
	}
	resp := &domain.SimpleResponse{}
	err = json.Unmarshal(respBytes, resp)
	if err != nil {
		logger.Errorf("音柱服务删除任务响应解析失败，%s", err.Error())
		return constant.DefaultFailureCode, err
	}
	if resp.Code != 200 {
		logger.Errorf("音柱服务删除任务响应解析失败，%s", resp.Message)
		return constant.DefaultFailureCode, err
	}
	return resp.Code, nil
}

func checkUrl(server string) string {
	upperUrl := strings.ToUpper(server)
	existHttp := strings.HasPrefix(upperUrl, "HTTP")
	if existHttp {
		return server
	} else {
		return "http://" + server
	}
}
